import javax.swing.JPanel;
import java.awt.event.*;
import java.awt.event.MouseAdapter;
import java.awt.*;
import java.awt.geom.Point2D;
import javax.swing.JOptionPane;

// for debug:      panel.setBackground(Color.red);

public class MouseListener extends MouseAdapter {
   private MyWorld world;
   private Drawable currentElement;
   private JPanel panel;
   public MouseListener (MyWorld w, JPanel p){
      world = w;
      panel = p;
   }
   /** este metodo permite seleccionar un objeto al posar el mouse encima de el
    *
    * @param e
    */
   public void mouseMoved(MouseEvent e) {
      Point2D.Double p = new Point2D.Double(0,0);
      MyWorld.SPACE_INVERSE_TRANSFORM.transform(e.getPoint(),p);
      Drawable newElement = world.find(p.getX(), p.getY());
      if (newElement == currentElement) return;
      if (currentElement != null) {
         currentElement.setReleased();
         currentElement = null;
      }
      if (newElement != null) { 
         currentElement = newElement;
         currentElement.setSelected();
       
      }
      panel.repaint();
   }
   /** este evento se activa cuando se arrastra un objeto.
    *
    * @param e
    */

   public void mouseDragged(MouseEvent e) {
      Point2D.Double p = new Point2D.Double(0,0);
      MyWorld.SPACE_INVERSE_TRANSFORM.transform(e.getPoint(),p);
      if (currentElement == null) return;
      currentElement.dragTo(p.getX(), p.getY());
      panel.repaint();
   }


   /** este evento se activa al soltar (release) el mouse sobre un elemento.
    *
    * @param e
    */
   public void mouseReleased(MouseEvent e) {
      if (currentElement != null) {
         currentElement.setReleased();
         /**
          * si el cursor detectado es de tipo crosshair, se activa el metodo remove.
          */
         if(panel.getCursor().getType() == Cursor.CROSSHAIR_CURSOR){
              world.remove((PhysicsElement) currentElement);
              panel.repaint();
              panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
         }
         
         if(panel.getCursor().getType() == Cursor.WAIT_CURSOR){
              world.selected((PhysicsElement) currentElement);
              panel.repaint();
              panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
         }
         /**
          * si el cursor detectado es de tipo hand,  se activa el metodo edit.
          */
         if(panel.getCursor().getType() == Cursor.HAND_CURSOR){
             String data=null;
             if(currentElement instanceof Ball) data = JOptionPane.showInputDialog("Enter Mass [Kg]","1");
             if(currentElement instanceof Rubber) data = JOptionPane.showInputDialog("Enter Stiffness [N/m]","20");
             if(currentElement instanceof Spring) data = JOptionPane.showInputDialog("Enter Stiffness [N/m]","20");
             world.edit(data, (PhysicsElement) currentElement);
              panel.repaint();
              panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
         }

      }
      if(currentElement == null){
         if(panel.getCursor().getType() == Cursor.CROSSHAIR_CURSOR || panel.getCursor().getType() == Cursor.HAND_CURSOR || panel.getCursor().getType() == Cursor.WAIT_CURSOR){
              panel.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
         }
      }
      if (!((currentElement instanceof GSpring) || (currentElement instanceof GRubber))) {
         currentElement = null;

         return;
      }


      Point2D.Double p= new Point2D.Double(0,0);
      MyWorld.SPACE_INVERSE_TRANSFORM.transform(e.getPoint(),p);

          // we dragged an attachable element
          // we dragged a spring, so we look for and attachable element near by  
      AttachableElement element = world.findAttachableElement(p.getX(), p.getY());
      if (element == null) {
         currentElement = null;
         return;
      }
      // we dragged a spring and it is near an attachable element,
      // so we hook them to the right spring end.
      if(currentElement instanceof GSpring ){
      GSpring spring = (GSpring) currentElement;
      Vector2D a=spring.getAendPosition();
      if ((a.getX()==p.getX()) && (a.getY()==p.getY()))
         spring.attachAend(element);
      Vector2D b=spring.getBendPosition();
      if ((b.getX()==p.getX()) && (b.getY()==p.getY()))
         spring.attachBend(element);
       }
       else if(currentElement instanceof GRubber)
       {
      GRubber rubber = (GRubber) currentElement;
      Vector2D c=rubber.getAendPosition();
      if ((c.getX()==p.getX()) && (c.getY()==p.getY()))
         rubber.attachAend(element);
      Vector2D d=rubber.getBendPosition();
      if ((d.getX()==p.getX()) && (d.getY()==p.getY()))
         rubber.attachBend(element);
       }

      currentElement = null;
      panel.repaint();      
   }
}